using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using L=Pine.Lexer;
using Pine.Core;
using Pine.SourceParser;
using Pine.SourceParser.Tree;
using Pine.CodeGen;

namespace Pine.Compiler.Utils
{
	public static class Compiler
	{		
		public static Document CreateDocument(string document, out int errorCount) {
			TokenQueue q = new TokenQueue();
			new L.Lexer(document, q);
			CodeParser p = new CodeParser(q);
			return p.parse_document(out errorCount);
		}
		
		public static Document CreateDocumentFromFile(string filename, out int errorCount) {
			return CreateDocumentFromFile(filename, Encoding.UTF8, out errorCount);
		}
		
		public static Document CreateDocumentFromFile(string filename, Encoding encoding, out int errorCount) {
			TokenQueue q = new TokenQueue();
			new L.Lexer(new StreamReader(filename, encoding), q);
			CodeParser p = new CodeParser(q);
			return p.parse_document(out errorCount);
		}
		
		public static CodeGenerator GenerateCode(string assemblyName, Document document, IList<Library> libraries) {
			return GenerateCode(assemblyName, document, libraries.ToArray());
		}
		
		public static CodeGenerator GenerateCode(string assemblyName, Document document, Library[] libraries) {
			return new CodeGenerator(assemblyName, document, libraries);
		}
		
		public static CodeGenerator GenerateCodeFromString(string assemblyName, string document, IList<Library> libraries) {
			return GenerateCodeFromString(assemblyName, document, libraries.ToArray());
		}
		
		public static CodeGenerator GenerateCodeFromString(string assemblyName, string document, Library[] libraries, out int errorCount) {
			return GenerateCode(assemblyName, CreateDocument(document, out errorCount), libraries);
		}
		
		public static CodeGenerator GenerateCodeFromFile(string assemblyName, string filename, IList<Library> libraries) {
			return GenerateCodeFromFile(assemblyName, filename, Encoding.UTF8, libraries);
		}
		
		public static CodeGenerator GenerateCodeFromFile(string assemblyName, string filename, Library[] libraries) {
			return GenerateCodeFromFile(assemblyName, filename, Encoding.UTF8, libraries);
		}
		
		public static CodeGenerator GenerateCodeFromFile(string assemblyName, string filename, Encoding encoding, IList<Library> libraries) {
			return GenerateCodeFromFile(assemblyName, filename, encoding, libraries);
		}
		
		public static CodeGenerator GenerateCodeFromFile(string assemblyName, string filename, Encoding encoding, Library[] libraries, out int errorCount) {
			return GenerateCode(assemblyName, CreateDocumentFromFile(filename, encoding, out errorCount), libraries);
		}
		
		public static void ExecuteString(string assemblyName, string function, string document, ValueList rl, Library[] libraries) {
			bool useLibraries = libraries != null;
			Library[] effectiveLibraries = libraries ?? new Library[0];
			
			int errorCount;
			CodeGenerator cg = GenerateCodeFromString(assemblyName, document, effectiveLibraries, out errorCount);
			
			if (errorCount == 0)
				cg.ExecuteFunction(function, rl, useLibraries);
			else
				throw new Exception("Lexer errors: " + errorCount);
		}
	}
}

